package com.innovation.ic.cyz.base.service.cyz.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.innovation.ic.cyz.base.mapper.cyz.MfrContentMapper;
import com.innovation.ic.cyz.base.mapper.cyz.MfrMapper;
import com.innovation.ic.cyz.base.mapper.cyz.MfrParamMapper;
import com.innovation.ic.cyz.base.model.cyz.Mfr;
import com.innovation.ic.cyz.base.model.cyz.MfrContent;
import com.innovation.ic.cyz.base.model.cyz.MfrParam;
import com.innovation.ic.cyz.base.pojo.annotation.MfrParamCode;
import com.innovation.ic.cyz.base.pojo.global.ServiceResult;
import com.innovation.ic.cyz.base.pojo.variable.cyz.MfrBackEndPageListPojo;
import com.innovation.ic.cyz.base.pojo.variable.cyz.MfrPcbOurProductPojo;
import com.innovation.ic.cyz.base.pojo.variable.cyz.MfrPcbSmtListPojo;
import com.innovation.ic.cyz.base.service.cyz.MfrBackEndService;
import com.innovation.ic.cyz.base.vo.cyz.AddMfrBackEndVo;
import com.innovation.ic.cyz.base.vo.cyz.MfrBackEndPageVo;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class MfrBackEndServiceImpl implements MfrBackEndService {

    @Resource
    private MfrMapper mfrMapper;

    @Resource
    private MfrParamMapper mfrParamMapper;

    @Resource
    private MfrContentMapper mfrContentMapper;

    @Resource
    private ServiceHelper serviceHelper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult addMfrBackEndVo(AddMfrBackEndVo addMfrBackEndVo) {
        ServiceResult serviceResult = new ServiceResult();
        Long mfrId = this.deleteMfrContent(addMfrBackEndVo);
        //拿到对象所有属性
        Field[] fields = addMfrBackEndVo.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                //字段名字
                String name = field.getName();
                //字段类型
                String typeName = field.getGenericType().getTypeName();
                //如果包含model不往数据库存
                if ("module".equals(name)) {
                    continue;
                }
                //如果是List,单独处理list数据
                if ("java.util.List<java.lang.String>".equals(typeName)) {
                    this.bindmfrParamList(mfrId, this.bindmfrParamMap(field, addMfrBackEndVo), addMfrBackEndVo.getModule());
                    continue;
                }
                //单独处理我的产品属性
                if ("ourProducts".equals(name)) {
                    this.bindmfrParamOurProducts(mfrId, addMfrBackEndVo.getOurProducts(), addMfrBackEndVo.getModule());
                    continue;
                }
                //注解别名
                Map<String, Object> stringObjectMap = this.bindmfrParamMap(field, addMfrBackEndVo);
                //找到类型所属id
                MfrParam mfrParam = mfrParamMapper.findByCodeAndModule(stringObjectMap.get("annotationValue"), addMfrBackEndVo.getModule());
                if (mfrParam == null) {
                    continue;
                }
                MfrContent mfrContent = new MfrContent();
                mfrContent.setMfrId(mfrId);
                mfrContent.setMfrParamId(mfrParam.getId());
                mfrContent.setContent(stringObjectMap.get("fieldValue") == null ? "" : stringObjectMap.get("fieldValue") + "");
                mfrContent.setOrderIndex(mfrParam.getOrderIndex());
                mfrContentMapper.insert(mfrContent);
            } catch (Exception e) {
                log.error("addMfrBackEndVo 发送异常", e);
            }
        }
        serviceResult.setSuccess(Boolean.TRUE);
        return serviceResult;
    }


    /**
     * 是否需要删除参数
     *
     * @param addMfrBackEndVo
     * @return
     */
    private Long deleteMfrContent(AddMfrBackEndVo addMfrBackEndVo) {
        Long mfrId = addMfrBackEndVo.getMfrId();
        if (mfrId == null) {
            //先添加一行记录
            Mfr mfr = new Mfr();
            mfr.setStatus(2);
            mfr.setModule(addMfrBackEndVo.getModule());
            mfr.setCreator_id(1);
            mfr.setCreate_date(new Date());
            mfrMapper.insertReturnId(mfr);
            mfrId = mfr.getId();
        } else {
            //删除原先参数值
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("mfr_id", mfrId);
            mfrContentMapper.deleteByMap(paramMap);
        }
        return mfrId;
    }


    @Override
    public void deleteMfrBackEnd(Long mfrId) {
        if (mfrId == null) {
            return;
        }
        mfrMapper.deleteById(mfrId);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("mfr_id", mfrId);
        mfrContentMapper.deleteByMap(paramMap);
    }

    @Override
    public ServiceResult<MfrBackEndPageListPojo> findByPage(MfrBackEndPageVo mfrBackEndPageVo) throws Exception {
        ServiceResult<MfrBackEndPageListPojo> serviceResult = new ServiceResult<>();

        //先分页查询mfr
        PageHelper.startPage(mfrBackEndPageVo.getPageNum(), mfrBackEndPageVo.getPageSize());
        List<Mfr> mfrList = mfrMapper.findByPage(mfrBackEndPageVo);
        PageInfo<Mfr> pageInfo = new PageInfo<>(mfrList);
        List<Mfr> pageList = pageInfo.getList();
        List<MfrPcbSmtListPojo> resultList = new ArrayList<>();

        //组装返回list
        if (!CollectionUtils.isEmpty(pageList)) {
            for (Mfr mfr : pageList) {
                //找出这个id下所有的content
                Map<String, Object> param = new HashMap<>();
                param.put("mfr_id", mfr.getId());
                List<MfrContent> mfrContents = mfrContentMapper.selectByMap(param);
                serviceHelper.getMfrParamDictionary().addCodes(mfr.getModule());
                MfrPcbSmtListPojo mfrPcbSmtListPojo = new MfrPcbSmtListPojo();
                mfrPcbSmtListPojo.setMfrId(mfr.getId());
                mfrPcbSmtListPojo.setModule(mfr.getModule());
                mfrPcbSmtListPojo.setCreatorTime(mfr.getCreate_date());
                // 给加了注解的字段赋值
                Field[] fields = mfrPcbSmtListPojo.getClass().getDeclaredFields();
                for (var field : fields) {
                    var annotation = field.getAnnotation(MfrParamCode.class);
                    if (annotation != null) {
                        Field f = MfrPcbSmtListPojo.class.getDeclaredField(field.getName());
                        String typeName = f.getGenericType().getTypeName();
                        if (typeName.equals("java.lang.String")) {
                            var content = getMfrContentByCode(mfrContents, mfr.getId(), annotation.value());
                            if (content != null) {
                                f.setAccessible(true);
                                f.set(mfrPcbSmtListPojo, content.getContent());
                            }
                        } else if (typeName.equals("java.util.List<java.lang.String>")) {
                            List<MfrContent> contents = getMfrContentsByCode(mfrContents, mfr.getId(), annotation.value());
                            if (contents != null && !contents.isEmpty()) {
                                List<String> stringList = contents.stream().map(MfrContent::getContent).collect(Collectors.toList());
                                f.setAccessible(true);
                                f.set(mfrPcbSmtListPojo, stringList);
                            }
                        }
                    }
                }
                resultList.add(mfrPcbSmtListPojo);
            }
        }
        MfrBackEndPageListPojo mfrBackEndPageListPojo = new MfrBackEndPageListPojo();
        mfrBackEndPageListPojo.setPages(pageInfo.getPages());
        mfrBackEndPageListPojo.setTotal(pageInfo.getTotal());
        mfrBackEndPageListPojo.setData(resultList);
        serviceResult.setSuccess(Boolean.TRUE);
        serviceResult.setResult(mfrBackEndPageListPojo);
        return serviceResult;
    }


    /**
     * 根据code获取MfrContent
     *
     * @param mfrContentList
     * @param mfrId
     * @param code
     * @return
     */
    private MfrContent getMfrContentByCode(List<MfrContent> mfrContentList, Long mfrId, String code) {
        return mfrContentList.stream()
                .filter(t -> t.getMfrId().equals(mfrId) && t.getMfrParamId().equals(serviceHelper.getMfrParamDictionary().getMfrParamIdByAllCode(code)))
                .findFirst().orElse(null);
    }

    /**
     * 根据code获取MfrContents
     *
     * @param mfrContentList
     * @param mfrId
     * @param code
     * @return
     */
    private List<MfrContent> getMfrContentsByCode(List<MfrContent> mfrContentList, Long mfrId, String code) {
        return mfrContentList.stream()
                .filter(t -> t.getMfrId().equals(mfrId) && t.getMfrParamId().equals(serviceHelper.getMfrParamDictionary().getMfrParamIdByAllCode(code)))
                .collect(Collectors.toList());
    }


    /**
     * 单独绑定我的产品参数
     *
     * @param mfrId
     */
    private void bindmfrParamOurProducts(Long mfrId, List<MfrPcbOurProductPojo> ourProducts, Integer module) throws Exception {
        if (CollectionUtils.isEmpty(ourProducts)) {
            return;
        }
        for (int i = 0; i < ourProducts.size(); i++) {
            //先保存主体
            MfrParam mfrParamRoot = mfrParamMapper.findByCodeAndModule("our_products_item", module);
            MfrContent saveMfrContentRoot = new MfrContent();
            saveMfrContentRoot.setMfrId(mfrId);
            saveMfrContentRoot.setMfrParamId(mfrParamRoot.getId());
            saveMfrContentRoot.setContent(mfrParamRoot.getName());
            saveMfrContentRoot.setGroupNo(i + 1);
            saveMfrContentRoot.setOrderIndex(i + 1);
            mfrContentMapper.insert(saveMfrContentRoot);

            MfrPcbOurProductPojo mfrPcbOurProductPojo = ourProducts.get(i);
            Field[] fields = mfrPcbOurProductPojo.getClass().getDeclaredFields();
            for (Field field : fields) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                if (field.getName().equals("serialVersionUID")) {
                    continue;
                }
                //字段名字
                Map<String, Object> paramMap = this.bindOurProductsParamMap(field, mfrPcbOurProductPojo);
                //找到父节点id
                Object fieldValue = paramMap.get("fieldValue");
                if (fieldValue == null) {
                    return;
                }
                MfrParam mfrParam = mfrParamMapper.findByCodeAndModule(paramMap.get("annotationValue"), module);
                MfrContent mfrContent = new MfrContent();
                mfrContent.setGroupNo(i + 1);
                mfrContent.setMfrId(mfrId);
                mfrContent.setMfrParamId(mfrParam.getId());
                mfrContent.setContent(fieldValue + "");
                mfrContentMapper.insert(mfrContent);
            }

        }
    }


    /**
     * 单独绑定List参数
     *
     * @param mfrId
     */
    private void bindmfrParamList(Long mfrId, Map<String, Object> paramMap, Integer module) {
        //找到父节点id
        Object fieldValue = paramMap.get("fieldValue");
        if (fieldValue == null) {
            return;
        }
        ArrayList<String> fieldValueList = (ArrayList<String>) fieldValue;
        for (String value : fieldValueList) {
            boolean mark = false;
            MfrParam mfrParam = mfrParamMapper.selectById(value);
            MfrContent mfrContent = new MfrContent();
            if (mfrParam == null) {
                mfrParam = mfrParamMapper.findByCodeAndModule(paramMap.get("annotationValue"), module);
                mark = true;
            }
            if (mfrParam == null) {
                continue;
            }
            if (mark) {
                mfrContent.setContent(value);
                mfrContent.setMfrParamId(mfrParam.getId());
            } else {
                mfrContent.setContent(mfrParam.getName());
                mfrContent.setMfrParamId(mfrParam.getParentId());
            }
            mfrContent.setMfrId(mfrId);
            mfrContentMapper.insert(mfrContent);
        }
    }


    /**
     * 转换当前属性值
     *
     * @return
     */
    private Map<String, Object> bindmfrParamMap(Field field, AddMfrBackEndVo addMfrBackEndVo) throws IllegalAccessException {
        Map<String, Object> result = new HashMap<>();
        //注解别名
        String annotationValue = "";
        //注解字段解释
        String annotationExplain = "";
        if (field.isAnnotationPresent(MfrParamCode.class)) {
            annotationValue = field.getAnnotation(MfrParamCode.class).value();
        }
        if (field.isAnnotationPresent(ApiModelProperty.class)) {
            annotationExplain = field.getAnnotation(ApiModelProperty.class).value();
        }
        System.out.println(field.getName() + ":" + field.get(addMfrBackEndVo) + ":" + annotationValue + ":" + annotationExplain);
        result.put("annotationValue", annotationValue);
        result.put("fieldValue", field.get(addMfrBackEndVo));
        result.put("annotationExplain", annotationExplain);
        return result;
    }


    /**
     * 转换当前属性值
     *
     * @return
     */
    private Map<String, Object> bindOurProductsParamMap(Field field, MfrPcbOurProductPojo mfrPcbOurProductPojo) throws IllegalAccessException {
        Map<String, Object> result = new HashMap<>();
        //注解别名
        String annotationValue = "";
        //注解字段解释
        String annotationExplain = "";
        if (field.isAnnotationPresent(MfrParamCode.class)) {
            annotationValue = field.getAnnotation(MfrParamCode.class).value();
        }
        if (field.isAnnotationPresent(ApiModelProperty.class)) {
            annotationExplain = field.getAnnotation(ApiModelProperty.class).value();
        }
        System.out.println(field.getName() + ":" + field.get(mfrPcbOurProductPojo) + ":" + annotationValue + ":" + annotationExplain);
        result.put("annotationValue", annotationValue);
        result.put("fieldValue", field.get(mfrPcbOurProductPojo));
        result.put("annotationExplain", annotationExplain);
        return result;
    }


}
